﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Collections;

namespace PartUpdater
{
    class HyperCopy
    {
        public void Copy(string from, string to)
        {
            const int copyBufferSize = 64 * 1024;

            if (File.Exists(to))
            {
                try
                {
                    File.Delete(to);
                }
                catch (Exception e)
                {
                    Console.Error.Write(e.Message);
                }
            }
                ASyncCopy(from, to, copyBufferSize);
        }

        private void ASyncCopy(string from, string to, int copyBufferSize)
        {
            FileInfo fi = new FileInfo(from);
            double fileSize = fi.Length;
            double copiedSize = 0;
            using (var outputFile = File.Create(to))
            {
                using (var inputFile = File.OpenRead(from))
                {
                    var buffer1 = new byte[copyBufferSize];
                    var buffer2 = new byte[copyBufferSize];
                    var inputBuffer = buffer1;
                    int bytesRead;
                    IAsyncResult writeResult = null;
                    while ((bytesRead = inputFile.Read(inputBuffer, 0, copyBufferSize)) != 0)
                    {
                        if (writeResult != null)
                        {
                            writeResult.AsyncWaitHandle.WaitOne();
                            outputFile.EndWrite(writeResult);
                            writeResult = null;
                        }
                        var outputBuffer = inputBuffer;
                        inputBuffer = (inputBuffer == buffer1) ? buffer2 : buffer1;
                        writeResult = outputFile.BeginWrite(outputBuffer, 0, bytesRead, null, null);
                        copiedSize += bytesRead;
                        ChangeProgress(copiedSize, fileSize);
                    }
                    if (writeResult != null)
                    {
                        writeResult.AsyncWaitHandle.WaitOne();
                        outputFile.EndWrite(writeResult);
                    }
                }
            }
        }

        private void ChangeProgress(double size, double mustCopySize)
        {
            Console.Write("\r{0}", arg0: (int)Math.Round(((size / mustCopySize) * 100)) + "%");
        }
    }
}
